package controller.invoice;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Observable;
import java.util.Observer;

import javax.swing.JOptionPane;
import javax.swing.table.DefaultTableModel;

import model.Customer;
import model.Invoice;
import model.InvoiceDetail;
import model.Laptop;
import model.Mobile;
import model.Product;
import model.Tablet;
import util.AutoCompleteDocument;
import util.MyRegex;
import view.invoice.InvoiceAddPanel;
import dao.CustomerDAO;
import dao.InvoiceDAO;
import dao.InvoiceDetailDAO;
import dao.LaptopDAO;
import dao.MobileDAO;
import dao.TabletDAO;
import date.MyDate;

public class InvoiceControl extends Observable implements ActionListener, MouseListener, KeyListener, Observer {

	private InvoiceAddPanel gui;
	private InvoiceDAO invoiceDAO;
	private InvoiceDetailDAO invoiceDetailDAO;
	private MobileDAO mobileDAO;
	private LaptopDAO laptopDAO;
	private TabletDAO tabletDAO;
	private CustomerDAO customerDAO;

	private Product product;
	private List<Product> listProduct;
	private DefaultTableModel dtm;

	private List<InvoiceDetail> listInvoiceDetails;

	public InvoiceControl(InvoiceAddPanel invoiceAdd) {
		this.gui = invoiceAdd;
		invoiceDAO = new InvoiceDAO();
		invoiceDetailDAO = new InvoiceDetailDAO();
		mobileDAO = new MobileDAO();
		tabletDAO = new TabletDAO();
		laptopDAO = new LaptopDAO();
		listProduct = new ArrayList<Product>();
		customerDAO = new CustomerDAO();

		resetValues();
		doCbbMobile();

		autoComplete();
	}

	private void resetValues() {
		listInvoiceDetails = new ArrayList<InvoiceDetail>();

		dtm = new DefaultTableModel();
		dtm.addColumn("Product ID");
		dtm.addColumn("Product name");
		dtm.addColumn("Quantity");
		dtm.addColumn("Price");

		gui.getTblInvaddInvoicedetail().setModel(dtm);
		gui.getTxtInvaddCustomerID().setText("");
		gui.getTxtInvaddQuantity().setText("");
		gui.getTxtInvaddTotal().setText("");
		gui.getTxtInvaddInvoiceid().setText("");
	}

	private void doCbbMobile() {

		listProduct.clear();
		gui.getCbbInvadd().removeAllItems();

		List<Mobile> list = mobileDAO.showAllMobile();
		List<Tablet> list2 = tabletDAO.showAllProduct();
		List<Laptop> list3 = laptopDAO.showAllProduct();

		if (list != null && list.size() != 0)
			product = list.get(0);
		else if (list2 != null && list2.size() != 0)
			product = list2.get(0);
		else if (list3 != null && list3.size() != 0)
			product = list3.get(0);
		else
			product = null;
		for (Mobile i : list) {
			gui.getCbbInvadd().addItem(i.getId());
			listProduct.add(i);
		}
		for (Tablet i : list2) {
			gui.getCbbInvadd().addItem(i.getId());
			listProduct.add(i);
		}
		for (Laptop i : list3) {
			gui.getCbbInvadd().addItem(i.getId());
			listProduct.add(i);
		}

	}

	@Override
	public void actionPerformed(ActionEvent event) {
		if (event.getSource() == gui.getBtnInvaddAdd()) {
			doSaveInvoice(event);
		} else if (event.getSource() == gui.getBtnInvaddAddnew()) {
			doSaveInvoiceDetail(event);
		} else if (event.getSource() == gui.getBtnInvaddCheck()) {
			doCheckInvoice(event);
		} else if (event.getSource() == gui.getBtnInvaddAddnew()) {
			doReset(event);
		} else if (event.getSource() == gui.getCbbInvadd()) {
			changeProduct();
		} else if (event.getSource() == gui.getBtnInvaddCancel()) {
			doReset(event);
		}
	}

	private void changeProduct() {
		for (Product i : listProduct) {
			if (gui.getCbbInvadd().getSelectedItem() != null) {
				if (i.getId().equals(gui.getCbbInvadd().getSelectedItem().toString())) {
					product = i;
					// System.out.println(i.getQuantity());
					break;
				}
			}
		}

		if (!gui.getTxtInvaddQuantity().getText().equals("") && product != null) {
			int quantity = Integer.parseInt(gui.getTxtInvaddQuantity().getText());

			if (isValidQuantity(quantity)) {
				String price = (product.getSalPrice() * quantity) + " ";
				gui.getTxtInvaddTotal().setText(price);
			} else {
				gui.getTxtInvaddQuantity().setText(product.getQuantity() + "");
			}
		}
	}

	private void doReset(ActionEvent event) {
		resetValues();
	}

	private void doCheckInvoice(ActionEvent event) {

	}

	private void searchCustomer() {
		if (!gui.getTxtInvaddCustomerID().getText().equals("")) {
			Customer cus = customerDAO.searchCustomer(gui.getTxtInvaddCustomerID().getText());
			if (cus != null) {
				found = true;
				gui.getTxtInvaddInvoiceid().setText(cus.getName());
			} else {
				found = false;
				gui.getTxtInvaddInvoiceid().setText("");
			}
		}
	}

	private double totalPrice;

	private void doSaveInvoiceDetail(ActionEvent event) {
		if (!gui.getTxtInvaddQuantity().getText().equals("") && product != null) {
			InvoiceDetail ivd = new InvoiceDetail();
			int quantity = Integer.parseInt(gui.getTxtInvaddQuantity().getText());
			double price = product.getSalPrice() * quantity;
			product.setQuantity(product.getQuantity() - quantity);
			totalPrice += price;
			ivd.setProductID(product.getId());
			ivd.setProductName(product.getName());
			ivd.setQuantity(quantity);
			ivd.setPrice(price);
			dtm.addRow(new Object[] { product.getId(), product.getName(), quantity, price });

			listInvoiceDetails.add(ivd);

			gui.getTblInvaddInvoicedetail().setModel(dtm);
		}

	}

	private void insertInvoice() {

		MyDate m = new MyDate();
		String date = m.getDate();
		Invoice in = new Invoice();

		in.setCustomerID(gui.getTxtInvaddCustomerID().getText());
		in.setCustomerName(gui.getTxtInvaddInvoiceid().getText());
		in.setDate(date);
		in.setTotal(totalPrice);
		invoiceDAO.insertInvoice(in);
		updateProduct();

		for (int i = 0; i < listInvoiceDetails.size(); i++) {
			listInvoiceDetails.get(i).setInvoice(in);
			invoiceDetailDAO.insertInvoiceDetail(listInvoiceDetails.get(i));
		}
		this.setChanged();
		this.notifyObservers();
		JOptionPane.showMessageDialog(gui, "Your invoice has been saved!!!", "Message", JOptionPane.INFORMATION_MESSAGE);
		resetValues();
	}

	private void updateProduct() {
		if (product instanceof Mobile) {
			mobileDAO.updateProduct((Mobile) product);
		} else if (product instanceof Tablet) {
			tabletDAO.updateProduct((Tablet) product);
		} else if (product instanceof Laptop) {
			laptopDAO.updateProduct((Laptop) product);
		}

		setChanged();
		notifyObservers();
	}

	private void doSaveInvoice(ActionEvent event) {
		if (gui.getTxtInvaddCustomerID().getText().equals("") && !gui.getTxtInvaddInvoiceid().getText().equals("")) {
			insertInvoice();
		} else if (!gui.getTxtInvaddCustomerID().getText().equals("") && found) {
			insertInvoice();
		} else if (!gui.getTxtInvaddCustomerID().getText().equals("")) {
			if (!found)
				JOptionPane.showConfirmDialog(gui, "Insert failed: If you don't have an account please leave the customer id blank", "Message", JOptionPane.WARNING_MESSAGE);
		}

	}

	@Override
	public void mouseClicked(MouseEvent e) {

	}

	@Override
	public void mouseEntered(MouseEvent e) {

	}

	@Override
	public void mouseExited(MouseEvent e) {

	}

	@Override
	public void mousePressed(MouseEvent e) {

	}

	@Override
	public void mouseReleased(MouseEvent e) {

	}

	@Override
	public void keyPressed(KeyEvent e) {
		handleKey(e);
	}
	
	private void handleKey(KeyEvent e){
		if (e.getSource() == gui.getTxtInvaddQuantity()) {
			String text = gui.getTxtInvaddQuantity().getText();
			if (text.length() != 0) {
				if (!MyRegex.isDigit(text)) {
					gui.getTxtInvaddQuantity().setText(text.substring(0, text.length() - 1));
				}
			} else if (text.length() == 0) {
				gui.getTxtInvaddQuantity().setText("0");
			}
			
			if (!gui.getTxtInvaddQuantity().getText().equals("") && product != null) {
				int quantity = Integer.parseInt(gui.getTxtInvaddQuantity().getText());
				if (isValidQuantity(quantity)) {
					String price = (product.getSalPrice() * quantity) + " ";
					gui.getTxtInvaddTotal().setText(price);
				} else {
					gui.getTxtInvaddQuantity().setText(product.getQuantity() + "");
				}
			}
			
		}
	}

	private boolean found = false;

	@Override
	public void keyReleased(KeyEvent e) {
		if (e.getSource() == gui.getTxtInvaddCustomerID()) {
			searchCustomer();
		}
		handleKey(e);

	}

	@Override
	public void keyTyped(KeyEvent e) {

	}

	@Override
	public void update(Observable o, Object arg) {
		doCbbMobile();

	}

	private boolean isValidQuantity(int quantity) {
		if (product == null)
			return false;
		return product.getQuantity() >= quantity;
	}

	private void autoComplete() {
		gui.getCbbInvadd().setEditable(true);
		new AutoCompleteDocument(gui.getCbbInvadd());
	}

}
